﻿using System;
using System.Threading.Tasks;


using System.Collections.Concurrent;

using Newtonsoft.Json;
using Sustainalytics.Utils;

namespace Sustainalytics.DataLayer
{
    public  class RepositoryLog
    {
        static private BlockingCollection<Loggable> logq;
        static private Task task;

        static RepositoryLog()
        {
            logq = new BlockingCollection<Loggable>();
            task = new Task(RepositoryLog.OnQueue);
            task.ContinueWith(RepositoryLog.OnContinue);
            task.Start();
        }
        static private void OnContinue(Task t)
        {
            if (t.IsFaulted)
            {
                CommonEventSource.Log.Exception(t.Exception);

                var newt = new Task(RepositoryLog.OnQueue);
                newt.ContinueWith(RepositoryLog.OnContinue);
                RepositoryLog.task = newt;
                RepositoryLog.task.Start();
            }

        }
        static private void OnQueue()
        {
            while (true)
            {
                var loggable = logq.Take();
                var text = string.Empty;
                try
                {
                    text = JsonConvert.SerializeObject(loggable, Formatting.Indented);                    
                }
                catch
                {//try again with strings only 
                    loggable.InputArgs = "Exception?";
                    loggable.Result = "Exception?";
                    text = JsonConvert.SerializeObject(loggable, Formatting.Indented);                    
                }
                CommonEventSource.Log.RepositoryEvent(text);
            }
        }

        static public void Log(string command, object input, object result, string dbname, string collection)
        {
            logq.Add(new Loggable() { Command = command, Database = dbname, CollectionOrTable = collection, InputArgs = input, Result = result });
        }

        static public void Log(string command, object input, Exception result, string dbname, string collection)
        {
            logq.Add(new Loggable() { Command = command, Database = dbname, CollectionOrTable = collection, InputArgs = input, Result = result });
        }

        class Loggable
        {
            public string Database { get; set; }
            public string CollectionOrTable { get; set; }
            public string Command { get; set; }
            public object InputArgs { get; set; }
            public object Result { get; set; }
        }
    }
}
